﻿/***************************************************************************************************/
/* @date on 2020-9-3 8:59:50                                                                       */
/* @author Xie Jian                                                                                */
/* @email 190954950@qq.com                                                                         */
/* @describe Sql作色                                                                               */
/***************************************************************************************************/
using CodeColorHtml.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeColorHtml.LanguageCulour
{
    /// <summary>
    /// Sql作色
    /// </summary>
    internal class CoulourSql : CoulourBase
    {
        public CoulourSql(string code) : base(code)
        {
            isSntistopLaw = false;
        }

        internal override string GetCodeColorHtml()
        {
            string newTemp = string.Empty;
            string newLineTemp = string.Empty;
            string codeSource = string.Empty;//原始代码
            int row = 0;
            if (_listCode != null && _listCode.Count > 0)
            {
                row = _listCode.Count;
                bool isAnnotationUnFinished = false;
                bool isCharacterUnFinished = false;
                string guidA = "53CAC3848E924099BC9B55013F62FDE8";
                string guidB = "53CAC3848E924099BC9B55013F62FDE9";
                for (int i = 0; i < _listCode.Count; i++)
                {
                    //处理单行
                    string item = "";
                    string itemTemp = "";
                    newLineTemp = $"<span style=\"width:45px;text-align:right;display:inline-block;border-right: 1px solid #CCCCCC; padding-right:5px;color:#D20169;margin-right:5px;\">{i + 1}</span>";

                    string tempItem = _listCode[i];
                    tempItem = tempItem.Replace("<", guidA).Replace(">", guidB);
                    CodeLine codeLine = GetCodeLine(tempItem, isAnnotationUnFinished, isCharacterUnFinished);
                    isAnnotationUnFinished = codeLine.IsAnnotationUnFinished;
                    isCharacterUnFinished = codeLine.IsCharacterUnFinished;


                    foreach (CodeSection section in codeLine.SectionList)
                    {
                        switch (section.SectionType)
                        {
                            case SectionType.Normal:
                                //关键词
                                List<string> listWord = GetWords(section.Text);
                                for (int j = 0; j < listWord.Count; j++)
                                {
                                    if (listWord[j] == " ")
                                    {
                                        item += "&nbsp;";
                                    }
                                    else
                                    {
                                        string color = GetColor(listWord[j]);
                                        if (string.IsNullOrEmpty(color))
                                        {
                                            item += listWord[j];
                                        }
                                        else
                                        {
                                            item += $"<span style=\"{color}\">{listWord[j]}</span>";
                                        }
                                    }
                                }
                                break;
                            case SectionType.Annotation:
                                string tempA = section.Text.Replace(" ", "&nbsp;");
                                item += $"<span style=\"{GetColorAnnotation()}\">{tempA}</span>";
                                break;
                            case SectionType.Character:
                                string tempC = section.Text.Replace(" ", "&nbsp;");
                                item += $"<span style=\"{GetColorCharacter()}\">{tempC}</span>";
                                break;
                            default:
                                break;
                        }
                    }

                    if (string.IsNullOrEmpty(item))
                    {
                        item = "&nbsp;";
                    }

                    item = item.Replace(guidA, "&lt;").Replace(guidB, "&gt;");
                    itemTemp = $"<div>{newLineTemp}{item}</div>";
                    newTemp += itemTemp;

                    codeSource += tempItem.Replace(guidA, "&lt;").Replace(guidB, "&gt;");
                    if (i < _listCode.Count - 1)
                    {
                        codeSource += "\r\n";
                    }
                }
            }

            string div = "<div class=\"code_chunk\"><div style=\"padding-left:40px;border-bottom: 1px solid #CCCCCC;\"><span class=\"code_chunk_copy\" style=\"cursor:pointer;color:cornflowerblue;\">复制代码</span></div>";            
            div += $"<div class=\"code_show\" style=\"overflow-x:auto;\">{newTemp}</div>";
            div += $"<div class=\"code_text\" style=\"display:none;\"><textarea style=\"width:100%;\" rows=\"{row}\" readonly=\"readonly\">{codeSource}</textarea></div></div>";
            return div;
        }

        private CodeLine GetCodeLine(string tempItem, bool isAnnotationUnFinished, bool isCharacterUnFinished)
        {
            CodeLine line = new CodeLine();
            if (isAnnotationUnFinished)
            {
                string value = tempItem;
                string annotATemp = value;
                int indexAnnotA = annotATemp.IndexOf("*/");
                if (indexAnnotA >= 0)
                {
                    string annotA = annotATemp.Substring(0, indexAnnotA + 2);
                    CodeSection sectionAnnotA = new CodeSection();
                    sectionAnnotA.Text = annotA;
                    sectionAnnotA.SectionType = SectionType.Annotation;
                    line.SectionList.Add(sectionAnnotA);
                    value = annotATemp.Substring(indexAnnotA + 2, annotATemp.Length - indexAnnotA - 2);
                    GetCodeLineNormal(value, line);
                }
                else
                {
                    CodeSection sectionAnnotA = new CodeSection();
                    sectionAnnotA.Text = annotATemp;
                    sectionAnnotA.SectionType = SectionType.Annotation;
                    line.SectionList.Add(sectionAnnotA);
                    line.IsAnnotationUnFinished = true;
                    value = string.Empty;
                }
            }
            else if (isCharacterUnFinished)
            {
                string value = tempItem;
                string charATemp = value;
                string guidA = "[Guid(53CAC384-8E92-4099-BC9B-55013F62FDE6)]";
                charATemp = charATemp.Replace("\\\"", guidA);
                int indexCharA = charATemp.IndexOf("\"");
                if (indexCharA >= 0)
                {
                    string charA = charATemp.Substring(0, indexCharA + 1);
                    CodeSection sectionCharA = new CodeSection();
                    sectionCharA.Text = charA.Replace(guidA, "\\\"");
                    sectionCharA.SectionType = SectionType.Character;
                    line.SectionList.Add(sectionCharA);
                    value = charATemp.Substring(indexCharA + 1, charATemp.Length - indexCharA - 1);
                    GetCodeLineNormal(value, line);
                }
                else
                {
                    CodeSection sectionCharA = new CodeSection();
                    sectionCharA.Text = charATemp.Replace(guidA, "\\\"");
                    sectionCharA.SectionType = SectionType.Character;
                    line.SectionList.Add(sectionCharA);
                    line.IsCharacterUnFinished = true;
                    value = string.Empty;
                }
            }
            else
            {
                GetCodeLineNormal(tempItem, line);
            }
            return line;
        }

        private void GetCodeLineNormal(string tempItem, CodeLine line)
        {
            string value = tempItem;
            while (!string.IsNullOrEmpty(value))
            {
                AnnotationIndex indexAnnotation = GetAnnotationIndex(value);
                CharacterIndex indexCharacter = GetCharacterIndex(value);
                bool isAnnotation = false;
                bool isCharacter = false;
                //注释
                if (indexAnnotation.Index >= 0)
                {
                    isAnnotation = true;
                }
                //字符串
                if (indexCharacter.Index >= 0)
                {
                    if (indexAnnotation.Index >= 0)
                    {
                        if (indexCharacter.Index < indexAnnotation.Index)
                        {
                            isCharacter = true;
                            isAnnotation = false;
                        }
                    }
                    else
                    {
                        isCharacter = true;
                        isAnnotation = false;
                    }
                }

                //注释
                if (isAnnotation)
                {
                    string text = value.Substring(0, indexAnnotation.Index);
                    if (!string.IsNullOrEmpty(text))
                    {
                        CodeSection section = new CodeSection();
                        section.Text = text;
                        section.SectionType = SectionType.Normal;
                        line.SectionList.Add(section);
                    }

                    switch (indexAnnotation.Type)
                    {
                        case AnnotationType.A:
                            string annotATemp = value.Substring(indexAnnotation.Index, value.Length - indexAnnotation.Index);
                            int indexAnnotA = annotATemp.IndexOf("*/");
                            if (indexAnnotA >= 0)
                            {
                                string annotA = annotATemp.Substring(0, indexAnnotA + 2);
                                CodeSection sectionAnnotA = new CodeSection();
                                sectionAnnotA.Text = annotA;
                                sectionAnnotA.SectionType = SectionType.Annotation;
                                line.SectionList.Add(sectionAnnotA);
                                value = annotATemp.Substring(indexAnnotA + 2, annotATemp.Length - indexAnnotA - 2);
                            }
                            else
                            {
                                CodeSection sectionAnnotA = new CodeSection();
                                sectionAnnotA.Text = annotATemp;
                                sectionAnnotA.SectionType = SectionType.Annotation;
                                line.SectionList.Add(sectionAnnotA);
                                line.IsAnnotationUnFinished = true;
                                value = string.Empty;
                            }
                            break;
                        case AnnotationType.B:
                            string annotB = value.Substring(indexAnnotation.Index, value.Length - indexAnnotation.Index);
                            CodeSection sectionAnnotB = new CodeSection();
                            sectionAnnotB.Text = annotB;
                            sectionAnnotB.SectionType = SectionType.Annotation;
                            line.SectionList.Add(sectionAnnotB);
                            value = string.Empty;
                            break;
                        case AnnotationType.C:
                            string annotC = value.Substring(indexAnnotation.Index, value.Length - indexAnnotation.Index);
                            CodeSection sectionAnnotC = new CodeSection();
                            sectionAnnotC.Text = annotC;
                            sectionAnnotC.SectionType = SectionType.Annotation;
                            line.SectionList.Add(sectionAnnotC);
                            value = string.Empty;
                            break;
                        default:
                            break;
                    }
                }
                else if (isCharacter)
                {
                    //字符串
                    string text = value.Substring(0, indexCharacter.Index);
                    if (!string.IsNullOrEmpty(text))
                    {
                        CodeSection section = new CodeSection();
                        section.Text = text;
                        section.SectionType = SectionType.Normal;
                        line.SectionList.Add(section);
                    }
                    switch (indexCharacter.Type)
                    {
                        case CharacterType.A:
                            string charATemp = value.Substring(indexCharacter.Index + 1, value.Length - indexCharacter.Index - 1);
                            string guidA = "[Guid(53CAC384-8E92-4099-BC9B-55013F62FDE6)]";
                            charATemp = charATemp.Replace("\\\"", guidA);
                            int indexCharA = charATemp.IndexOf("\"");
                            if (indexCharA >= 0)
                            {
                                string charA = charATemp.Substring(0, indexCharA + 1);
                                CodeSection sectionCharA = new CodeSection();
                                sectionCharA.Text = "\"" + charA.Replace(guidA, "\\\"");
                                sectionCharA.SectionType = SectionType.Character;
                                line.SectionList.Add(sectionCharA);
                                value = charATemp.Substring(indexCharA + 1, charATemp.Length - indexCharA - 1);
                            }
                            else
                            {
                                CodeSection sectionCharA = new CodeSection();
                                sectionCharA.Text = "\"" + charATemp.Replace(guidA, "\\\"");
                                sectionCharA.SectionType = SectionType.Character;
                                line.SectionList.Add(sectionCharA);
                                line.IsCharacterUnFinished = true;
                                value = string.Empty;
                            }
                            break;
                        case CharacterType.B:
                            string charBTemp = value.Substring(indexCharacter.Index + 1, value.Length - indexCharacter.Index - 1);
                            string guidB = "[Guid(53CAC384-8E92-4099-BC9B-55013F62FDE7)]";
                            charBTemp = charBTemp.Replace("\\\'", guidB);
                            int indexCharB = charBTemp.IndexOf("\'");
                            if (indexCharB >= 0)
                            {
                                string charB = charBTemp.Substring(0, indexCharB + 1);
                                CodeSection sectionCharB = new CodeSection();
                                sectionCharB.Text = "\'" + charB.Replace(guidB, "\\\'");
                                sectionCharB.SectionType = SectionType.Character;
                                line.SectionList.Add(sectionCharB);
                                value = charBTemp.Substring(indexCharB + 1, charBTemp.Length - indexCharB - 1);
                            }
                            else
                            {
                                CodeSection sectionCharB = new CodeSection();
                                sectionCharB.Text = "\'" + charBTemp.Replace(guidB, "\\\'");
                                sectionCharB.SectionType = SectionType.Character;
                                line.SectionList.Add(sectionCharB);
                                line.IsCharacterUnFinished = true;
                                value = string.Empty;
                            }
                            break;
                        default:
                            break;
                    }
                }
                else
                {
                    //普通
                    CodeSection section = new CodeSection();
                    section.Text = value;
                    section.SectionType = SectionType.Normal;
                    line.SectionList.Add(section);
                    value = string.Empty;
                }
            }
        }

        #region 关键词
        /// <summary>
        /// 关键词
        /// </summary>
        /// <returns></returns>
        protected override string Sntistop()
        {
            string values = @"
add,
all,
alter,
and,
as,
asc,
avg,
begin,
between,
blob,
by,
cache,
char,
clob,
close,
column,
comment,
constraint,
corss,
count,
create,
cursor,
date,
default,
delete,
desc, 
distinct,
double,
drop,
end,
except,
exit,
fetch,
float,
for,
foreign,
from,
full,
function,
group,
having,
if,
in,
increment,
inner, 
integer,
insert,
is,  
int,
intersect,    
into,
join,
key,
left,
length,
loop,
max,
maxvalue,
min,
minvalue,
natural, 
not,
null, 
number,
numeric,
nvarchar,
nvarchar2,
on,
open,
or,
order,
outer,
precision,
primary,
real,
ref,
references,
replace,
return,
right,
select,
sequence,
set,
smallint,
start,
sum,
table,
then,
truncate,
type,
union,
update,
using,
values,
varchar,
varchar2,
with,
when,
where";
            return values;
        }
        #endregion

        /// <summary>
        /// 获取注释的开始位置
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        protected AnnotationIndex GetAnnotationIndex(string text)
        {
            List<AnnotationIndex> list = new List<AnnotationIndex>();
            int index1 = text.IndexOf("/*");
            int index2 = text.IndexOf("--");
            //int index3 = text.IndexOf("#");
            list.Add(new AnnotationIndex() { Index = index1, Type = AnnotationType.A });
            list.Add(new AnnotationIndex() { Index = index2, Type = AnnotationType.B });
            //list.Add(new AnnotationIndex() { Index = index3, Type = AnnotationType.C });
            AnnotationIndex index = list.Where(t => t.Index >= 0).OrderBy(t => t.Index).FirstOrDefault();
            if (index == null)
            {
                index = new AnnotationIndex() { Index = -1, Type = AnnotationType.A };
            }
            return index;
        }

        /// <summary>
        /// 获取字符字符串的开始位置
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        protected CharacterIndex GetCharacterIndex(string text)
        {
            List<CharacterIndex> list = new List<CharacterIndex>();
            int index1 = text.IndexOf("\"");
            int index2 = text.IndexOf("'");
            list.Add(new CharacterIndex() { Index = index1, Type = CharacterType.A });
            list.Add(new CharacterIndex() { Index = index2, Type = CharacterType.B });
            CharacterIndex index = list.Where(t => t.Index >= 0).OrderBy(t => t.Index).FirstOrDefault();
            if (index == null)
            {
                index = new CharacterIndex() { Index = -1, Type = CharacterType.A };
            }
            return index;
        }
    }
}
